#ifndef _ICMP_H_
#define _ICMP_H_

#include <crt_util.h>
#include "ip.h"

#ifdef __cplusplus
extern "C" {
#endif

//----------------------icmp----------------------------------
#define ICMP_ECHOREPLY      0  /* Echo Reply            */
#define ICMP_DEST_UNREACH   3  /* Destination Unreachable    */
#define ICMP_SOURCE_QUENCH  4  /* Source Quench        */
#define ICMP_REDIRECT       5  /* Redirect (change route)    */
#define ICMP_ECHO           8  /* Echo Request            */
#define ICMP_TIME_EXCEEDED  11 /* Time Exceeded        */
#define ICMP_PARAMETERPROB  12 /* Parameter Problem        */
#define ICMP_TIMESTAMP      13 /* Timestamp Request        */
#define ICMP_TIMESTAMPREPLY 14 /* Timestamp Reply        */
#define ICMP_INFO_REQUEST   15 /* Information Request        */
#define ICMP_INFO_REPLY     16 /* Information Reply        */
#define ICMP_ADDRESS        17 /* Address Mask Request        */
#define ICMP_ADDRESSREPLY   18 /* Address Mask Reply        */

// sizeof(icmphdr_t) = 8
typedef struct icmphdr_s {
    uint8_t type; // message type
    uint8_t code; // type sub-code
    uint16_t checksum;
    union {
        struct {
            uint16_t id;
            uint16_t sequence;
        } echo;
        uint32_t gateway;
        struct {
            uint16_t reserved;
            uint16_t mtu;
        } frag;
    } un;
} icmphdr_t;

typedef struct icmp_s {
    uint8_t icmp_type;
    uint8_t icmp_code;
    uint16_t icmp_cksum;
    union {
        uint8_t ih_pptr;
        struct in_addr ih_gwaddr;
        struct ih_idseq {
            uint16_t icd_id;
            uint16_t icd_seq;
        } ih_idseq;
        uint32_t ih_void;

        struct ih_pmtu {
            uint16_t ipm_void;
            uint16_t ipm_nextmtu;
        } ih_pmtu;

        struct ih_rtradv {
            uint8_t irt_num_addrs;
            uint8_t irt_wpa;
            uint16_t irt_lifetime;
        } ih_rtradv;
    } icmp_hun;
#define icmp_pptr      icmp_hun.ih_pptr
#define icmp_gwaddr    icmp_hun.ih_gwaddr
#define icmp_id        icmp_hun.ih_idseq.icd_id
#define icmp_seq       icmp_hun.ih_idseq.icd_seq
#define icmp_void      icmp_hun.ih_void
#define icmp_pmvoid    icmp_hun.ih_pmtu.ipm_void
#define icmp_nextmtu   icmp_hun.ih_pmtu.ipm_nextmtu
#define icmp_num_addrs icmp_hun.ih_rtradv.irt_num_addrs
#define icmp_wpa       icmp_hun.ih_rtradv.irt_wpa
#define icmp_lifetime  icmp_hun.ih_rtradv.irt_lifetime

    union {
        struct {
            uint32_t its_otime;
            uint32_t its_rtime;
            uint32_t its_ttime;
        } id_ts;
        /*
        struct {
            struct ip idi_ip;
        } id_ip;
        struct icmp_ra_addr id_radv;
        */
        uint32_t id_mask;
        uint8_t id_data[1];
    } icmp_dun;
#define icmp_otime icmp_dun.id_ts.its_otime
#define icmp_rtime icmp_dun.id_ts.its_rtime
#define icmp_ttime icmp_dun.id_ts.its_ttime
#define icmp_ip    icmp_dun.id_ip.idi_ip
#define icmp_radv  icmp_dun.id_radv
#define icmp_mask  icmp_dun.id_mask
#define icmp_data  icmp_dun.id_data
} icmp_t;
// #endif

int ping(const char* host, int cnt /* DEFAULT(4)*/);

#ifdef __cplusplus
}
#endif

#endif // _ICMP_H_
